home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_sys5 / unixkit.tgz / unixkit.tar / unixkit / tundrvr / if_tun.c < prev    next >
C/C++ Source or Header  |  1991-12-05  |  15KB  |  657 lines

  1. /* if_tun.c - tunnel interface module & driver */
  2.  
  3. /*
  4.  * Copyright (c) 1988, Julian Onions. 
  5.  *
  6.  * This source may be freely distributed, however I would be interested
  7.  * in any changes that are made.
  8.  */
  9.  
  10. /*
  11.  * 91/12/05 - Disabled the test for super-user on open.  This posed more
  12.  * of a security risk than a benefit in some cases, as it encouraged
  13.  * developers to write (horrors!) suid root scripts and programs...
  14.  * Normal permissions on /dev/tun0 should suffice to control access.
  15.  * (The truly security consious shouldn't be running a tunnel driver anyway.)
  16.  * Mike Westerhof - Mike.Westerhof@Central.Sun.COM
  17.  *
  18.  * 90/02/06 15:03 - Fixed a bug in where TIOCGPGRP and TIOCSPGRP were
  19.  * mixed up. Anders Klemets - klemets@sics.se
  20.  *
  21.  * $Header: if_tun.c,v 1.13 88/07/11 08:28:51 jpo Exp $
  22.  * 
  23.  * $Log:    if_tun.c,v $
  24.  * Revision 1.13  88/07/11  08:28:51  jpo
  25.  * Some tidying up
  26.  * 
  27.  * Revision 1.12  87/12/10  09:16:29  jpo
  28.  * Decided the vax/mtpr was unnecessay.
  29.  * 
  30.  * Revision 1.11  87/12/10  09:10:36  jpo
  31.  * Fixed some minor things & 1 major bug.
  32.  * 
  33.  * Revision 1.10  87/11/04  14:27:41  jpo
  34.  * A few sanity checks added.
  35.  * 
  36.  * Revision 1.9  87/11/04  14:13:45  jpo
  37.  * Added some ioctls for non-blocking & async I/O
  38.  * 
  39.  * Revision 1.8     87/10/19  10:28:14  jpo
  40.  * Another touch up (sigh)
  41.  * 
  42.  * Revision 1.7     87/10/19  10:25:48  jpo
  43.  * Touch up.
  44.  * 
  45.  * Revision 1.6     87/10/19  09:15:14  jpo
  46.  * Touch up.
  47.  * 
  48.  * Revision 1.5     87/10/19  08:34:51  jpo
  49.  * General clean up - plus sun specific fixes
  50.  * 
  51.  * Revision 1.4     87/10/16  17:10:12  jpo
  52.  * Purged all ioctl read/writes and non-standard routing stuff.
  53.  *
  54.  * Revision 1.3     87/10/05  11:57:09  jpo
  55.  * More debugging - in error mainly.
  56.  * 
  57.  * Revision 1.2     87/10/04  18:29:45  jpo
  58.  * Select & read/write working.
  59.  */
  60.  
  61. #include "tun.h"
  62. #if NTUN > 0
  63.  
  64. /*
  65.  * Tunnel driver.
  66.  *
  67.  * This driver takes packets off the IP i/f and hands them up to a
  68.  * user process to have it's wicked way with. This driver has it's
  69.  * roots in a similar driver written by Phil Cockcroft (formerly) at
  70.  * UCL. This driver is based much more on read/write/select mode of
  71.  * operation though.
  72.  * 
  73.  * Julian Onions <jpo@cs.nott.ac.uk>
  74.  * Nottingham University 1987.
  75.  */
  76.  
  77. #define SUNOS4    /* explicitly defined here, because i didn't want to
  78.            change the kernel Makefiles */
  79.  
  80. #ifdef SUNOS4
  81. #define BSD4_3
  82. #endif /* SUNOS4 */
  83.  
  84. #ifdef SUNOS4
  85. #include <sys/param.h>
  86. #include <sys/systm.h>
  87. #include <sys/mbuf.h>
  88. #include <sys/file.h>
  89. #include <sys/socket.h>
  90. #include <sys/errno.h>
  91. #include <sys/ioctl.h>
  92. #include <sys/user.h>
  93. #include <sys/proc.h>
  94.  
  95. #include <net/if.h>
  96. #include <net/netisr.h>
  97. #include <net/route.h>
  98.  
  99. #include <netinet/in.h>
  100. #include <netinet/in_systm.h>
  101. #include <netinet/ip.h>
  102. #include <netinet/ip_var.h>
  103.  
  104. #include <sys/uio.h>
  105. #include <netinet/if_tnreg.h>
  106. #include <netinet/in_var.h>
  107. #else /* SUNOS4 */
  108. /* this may not work for BSD4_3 kernels */
  109. #include "../h/param.h"
  110. #include "../h/systm.h"
  111. #include "../h/mbuf.h"
  112. #include "../h/file.h"
  113. #include "../h/socket.h"
  114. #include "../h/errno.h"
  115. #include "../h/ioctl.h"
  116. #include "../h/user.h"
  117. #include "../h/proc.h"
  118.  
  119. #include "../net/if.h"
  120. #include "../net/netisr.h"
  121. #include "../net/route.h"
  122.  
  123. #include "../netinet/in.h"
  124. #include "../netinet/in_systm.h"
  125. #include "../netinet/ip.h"
  126. #include "../netinet/ip_var.h"
  127.  
  128. #include "../h/uio.h"
  129. #include "../netinet/if_tnreg.h"
  130. #endif /* SUNOS4 */
  131.  
  132. #define TUNDEBUG    if (tundebug) printf
  133.  
  134. int        tundebug = 0;
  135. struct tunctl
  136. {
  137.     u_short        tun_flags;    /* misc flags */
  138.     struct ifnet    tun_if;        /* the interface */
  139.     int        tun_pgrp;    /* the process group - if any */
  140.     struct proc    *tun_rsel;    /* read select */
  141.     struct proc    *tun_wsel;    /* write select (not used) */
  142. }    tunctl[NTUN];
  143.  
  144. extern int    ifqmaxlen;
  145.  
  146. int        tunoutput (), tunioctl (), tuninit ();
  147.  
  148. /* tunnel open - must be superuser & the device must be configured in */
  149. tunopen (dev, flag)
  150. dev_t        dev;
  151. {
  152.     register int    unit;
  153.     struct tunctl  *tp;
  154.     register struct ifnet *ifp;
  155.  
  156. /* Uncomment this check to limit access to the super-user.
  157.  * Normal installations can just live with permissions on /dev/tun?
  158.  * set via the chmod command... KA9WSB
  159.  */
  160. /*
  161.     if (!suser ())
  162.         return EACCES;
  163. */
  164.  
  165.     if ((unit = minor (dev)) >= NTUN)
  166.         return (ENXIO);
  167.     tp = &tunctl[unit];
  168.     if (tp->tun_flags & TUN_OPEN)
  169.         return ENXIO;
  170.     if ((tp->tun_flags & TUN_INITED) == 0) {
  171.         tp->tun_flags = TUN_INITED;
  172.         tunattach (unit);
  173.     }
  174.     ifp = &tp->tun_if;
  175.     tp->tun_flags |= TUN_OPEN;
  176.     TUNDEBUG ("%s%d: open\n", ifp->if_name, ifp->if_unit);
  177.     return (0);
  178. }
  179.  
  180. /* tunclose - close the device - mark i/f down & delete routing info */
  181. tunclose (dev, flag)
  182. dev_t        dev;
  183. {
  184.     int        s;
  185.     int        rcoll;
  186.     register int    unit = minor (dev);
  187.     register struct tunctl *tp = &tunctl[unit];
  188.     register struct ifnet *ifp = &tp->tun_if;
  189.     register struct mbuf *m;
  190. #ifdef BSD4_3
  191.     /*
  192.      * maybe we should verify here, that the af of the
  193.      * first entry in if_addrlist is indeed AF_INET.
  194.      */
  195.     struct in_ifaddr *ia =  (struct in_ifaddr *) ifp->if_addrlist;
  196. #endif
  197.  
  198.     rcoll = tp->tun_flags & TUN_RCOLL;
  199.     tp->tun_flags &= TUN_INITED;
  200.  
  201.     /*
  202.      * junk all pending output
  203.      */
  204.     do {
  205.         s = splimp ();
  206.         IF_DEQUEUE (&ifp->if_snd, m);
  207.         splx (s);
  208.         if (m) /* actually - m_freem checks this - but what the hell */
  209.             m_freem (m);
  210.     } while (m != 0);
  211.     if (ifp->if_flags & IFF_UP) {
  212.         s = splimp ();
  213.         if_down (ifp);
  214.         if (ifp->if_flags & IFF_RUNNING)
  215. #ifdef BSD4_3
  216.             rtinit( &ia->ia_dstaddr, &ia->ia_addr, (int)SIOCDELRT, RTF_HOST);
  217. #else /* ! BSD4_3 */
  218.             if_rtinit (ifp, -1);    /* delete routing info */
  219. #endif /* BSD4_3 */
  220.         splx (s);
  221.     }
  222.     tp -> tun_pgrp = 0;
  223.     if (tp -> tun_rsel)
  224.         selwakeup (tp->tun_rsel, rcoll);
  225.         
  226.     tp -> tun_rsel = tp -> tun_wsel = (struct proc *)0;
  227.  
  228.     TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
  229.     return (0);
  230. }
  231.  
  232. /*
  233.  * attach an interface N.B. argument is not same as other drivers
  234.  */
  235. int
  236. tunattach (unit)
  237. int        unit;
  238. {
  239.     register struct ifnet *ifp = &tunctl[unit].tun_if;
  240.     register struct sockaddr_in *sin;
  241.  
  242.     ifp->if_unit = unit;
  243.     ifp->if_name = "tun";
  244.     ifp->if_mtu = TUNMTU;
  245.     ifp->if_ioctl = tunioctl;
  246.     ifp->if_output = tunoutput;
  247.     ifp->if_init = tuninit;
  248. #ifndef BSD4_3
  249.     sin = (struct sockaddr_in *) & ifp->if_addr;
  250.     sin->sin_family = AF_INET;
  251. #endif
  252.     ifp->if_flags = IFF_POINTOPOINT;
  253.     ifp->if_snd.ifq_maxlen = ifqmaxlen;
  254.     ifp->if_collisions = ifp->if_ierrors = ifp->if_oerrors = 0;
  255.     ifp->if_ipackets = ifp->if_opackets = 0;
  256.     if_attach (ifp);
  257.     TUNDEBUG ("%s%d: tunattach\n", ifp->if_name, ifp->if_unit);
  258.     return 0;
  259. }
  260.  
  261. int
  262. tuninit (unit)
  263. int        unit;
  264. {
  265.     register struct tunctl *tp = &tunctl[unit];
  266.     register struct ifnet *ifp = &tp->tun_if;
  267. #ifndef BSD4_3
  268.     register struct sockaddr_in *sin;
  269.  
  270.     sin = (struct sockaddr_in *) & ifp->if_addr;
  271.     if (sin->sin_addr.s_addr == 0)    /* if address still unknown */
  272.         return;
  273.     if_rtinit (ifp, RTF_UP);
  274. #endif
  275.     ifp->if_flags |= IFF_UP | IFF_RUNNING;
  276.     tp->tun_flags |= TUN_IASET;
  277.     TUNDEBUG ("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
  278.     return 0;
  279. }
  280.  
  281. /*
  282.  * Process an ioctl request.
  283.  * The problem here is 4.2 pass a struct ifreq * to this routine,
  284.  * sun only passes a struct sockaddr * since 3.2 at least. This is
  285.  * rather upsetting! Also, sun doesn't pass the SIOCDSTADDR ioctl through
  286.  * so we can't detect this being set directly. This is the reason for
  287.  * tuncheckready.
  288.  * Under 4.3 and SunOs 4.0 we now get the SIOCSIFDSTADDR ioctl, and we get a
  289.  * struct in_ifaddr * for data. (tte)
  290.  */
  291.  
  292. #if !defined(BSD4_3) && defined(sun)
  293.  
  294. /*
  295.  * workaround for not being able to detect DSTADDR being set.
  296.  */
  297.  
  298. tuncheckready (ifp)
  299. struct ifnet *ifp;
  300. {
  301.     struct tunctl *tp = &tunctl[ifp->if_unit];
  302.     struct sockaddr_in *sin;
  303.  
  304.     sin = (struct sockaddr_in *) &ifp->if_dstaddr;
  305.     if (sin->sin_addr.s_addr == 0)
  306.         return 0;
  307.     tp -> tun_flags |= TUN_DSTADDR;
  308.     return 1;
  309. }
  310. #else
  311. #define tuncheckready(dummy) 1
  312. #endif /* !defined(BSD4_3) && defined(sun) */
  313.  
  314. int
  315. tunioctl (ifp, cmd, data)
  316. register struct ifnet *ifp;
  317. int        cmd;
  318. caddr_t        data;
  319. {
  320. #ifndef BSD4_3
  321. #ifdef sun    
  322.     struct sockaddr_in *sin = (struct sockaddr_in *) data;
  323. #else
  324.     struct sockaddr_in *sin;
  325.     struct ifreq    *ifr = (struct ifreq *) data;
  326. #endif
  327. #endif /* BSD4_3 */
  328.  
  329.     int        s = splimp (), error = 0;
  330.     struct tunctl  *tp = &tunctl[ifp->if_unit];
  331.  
  332.     switch (cmd)
  333.     {
  334.         case SIOCSIFADDR:
  335. #ifndef BSD4_3
  336.         if (ifp->if_flags & IFF_RUNNING)
  337.             if_rtinit (ifp, -1);    /* delete previous route */
  338. #ifndef sun
  339.         sin = (struct sockaddr_in *)&ifr -> ifr_addr;
  340. #endif
  341.         ifp->if_addr = *((struct sockaddr *) sin);
  342.         ifp->if_net = in_netof (sin->sin_addr);
  343.         ifp->if_host[0] = in_lnaof (sin->sin_addr);
  344. #endif
  345.         tuninit (ifp->if_unit);
  346.         break;
  347.         case SIOCSIFDSTADDR:
  348.         tp->tun_flags |= TUN_DSTADDR;
  349. #ifndef BSD4_3
  350. #ifndef sun
  351.         sin = (struct sockaddr_in *)&ifr -> ifr_addr;
  352. #endif
  353.         ifp->if_dstaddr = *((struct sockaddr *)sin);
  354. #endif BSD4_3
  355.         TUNDEBUG ("%s%d: destination addres set\n", ifp->if_name,
  356.             ifp -> if_unit);
  357.         break;
  358.         default:
  359.         error = EINVAL;
  360.     }
  361.     splx (s);
  362.     return (error);
  363. }
  364.  
  365. /*
  366.  * tunoutput - queue packets from higher level ready to put out.
  367.  */
  368. tunoutput (ifp, m0, dst)
  369. struct ifnet   *ifp;
  370. struct mbuf    *m0;
  371. struct sockaddr *dst;
  372. {
  373.     struct tunctl  *tp;
  374.     struct proc    *p;
  375.     int        s;
  376.  
  377.     TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
  378.     tp = &tunctl[ifp->if_unit];
  379.     if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  380.         if(tuncheckready(ifp) == 0) {
  381.             TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  382.                 ifp->if_unit, tp->tun_flags);
  383.             m_freem (m0);
  384.             return EHOSTDOWN;
  385.         }
  386.     }
  387.  
  388.     switch (dst->sa_family) {
  389. #ifdef INET
  390.         case AF_INET:
  391.         s = splimp ();
  392.         if (IF_QFULL (&ifp->if_snd))
  393.         {
  394.             IF_DROP (&ifp->if_snd);
  395.             m_freem (m0);
  396.             splx (s);
  397.             ifp->if_collisions++;
  398.             return (ENOBUFS);
  399.         }
  400.         IF_ENQUEUE (&ifp->if_snd, m0);
  401.         splx (s);
  402.         ifp->if_opackets++;
  403.         break;
  404. #endif
  405.         default:
  406.         m_freem (m0);
  407.         return EAFNOSUPPORT;
  408.     }
  409.  
  410.     if (tp->tun_flags & TUN_RWAIT) {
  411.         tp->tun_flags &= ~TUN_RWAIT;
  412.         wakeup ((caddr_t) tp);
  413.     }
  414.     if (tp->tun_flags & TUN_ASYNC && tp -> tun_pgrp != 0) {
  415.         if (tp->tun_pgrp > 0)
  416.             gsignal (tp->tun_pgrp, SIGIO);
  417.         else if ((p = pfind (-tp->tun_pgrp)) != 0)
  418.             psignal (p, SIGIO);
  419.     }
  420.     if (tp->tun_rsel) {
  421.         selwakeup (tp->tun_rsel, tp->tun_flags & TUN_RCOLL);
  422.         tp->tun_flags &= ~TUN_RCOLL;
  423.         tp->tun_rsel = (struct proc *) 0;
  424.     }
  425.     return 0;
  426. }
  427.  
  428. /*
  429.  * the cdevsw interface is now pretty minimal.
  430.  */
  431.  
  432. tuncioctl (dev, cmd, data, flag)
  433. dev_t        dev;
  434. caddr_t        data;
  435. {
  436.     int    unit = minor(dev);
  437.     struct tunctl *tp = &tunctl[unit];
  438.     int    s;
  439.  
  440.     switch (cmd) {
  441.         case TUNSDEBUG:
  442.         tundebug = *(int *)data;
  443.         break;
  444.  
  445.         case TUNGDEBUG:
  446.         *(int *)data = tundebug;
  447.         break;
  448.  
  449.         case FIONBIO:
  450.         if (*(int *)data)
  451.             tp->tun_flags |= TUN_NBIO;
  452.         else
  453.             tp->tun_flags &= ~TUN_NBIO;
  454.         break;
  455.  
  456.         case FIOASYNC:
  457.         if (*(int *)data)
  458.             tp->tun_flags |= TUN_ASYNC;
  459.         else
  460.             tp->tun_flags &= ~TUN_ASYNC;
  461.         break;
  462.  
  463.         case FIONREAD:
  464.         s = splimp ();
  465.         if (tp->tun_if.if_snd.ifq_head)
  466.             *(int *)data = tp->tun_if.if_snd.ifq_head->m_len;
  467.         else    *(int *)data = 0;
  468.         splx (s);
  469.         break;
  470.  
  471.         case TIOCSPGRP:
  472.         tp->tun_pgrp = *(int *)data;
  473.         break;
  474.  
  475.         case TIOCGPGRP:
  476.         *(int *)data = tp->tun_pgrp;
  477.         break;
  478.  
  479.         default:
  480.         return (ENOTTY);
  481.     }
  482.     return (0);
  483. }
  484.  
  485. /*
  486.  * The cdevsw read interface - reads a packet at a time, or at least as much
  487.  * of a packet as can be read.
  488.  */
  489. tunread (dev, uio)
  490. dev_t        dev;
  491. struct uio     *uio;
  492. {
  493.     register struct ifnet *ifp;
  494.     register struct mbuf *m, *m0;
  495.     int        unit = minor (dev);
  496.     int        len, s;
  497.     int        error = 0;
  498.     struct tunctl  *tp;
  499.  
  500.     tp = &tunctl[unit];
  501.     ifp = &tp->tun_if;
  502.     TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
  503.     if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  504.         if(tuncheckready(ifp) == 0) {
  505.             TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  506.                 ifp->if_unit, tp->tun_flags);
  507.             return EHOSTDOWN;
  508.         }
  509.     }
  510.  
  511.     tp->tun_flags &= ~TUN_RWAIT;
  512.  
  513.     s = splimp ();
  514.     do {
  515.         IF_DEQUEUE (&ifp->if_snd, m0);
  516.         if (m0 == 0) {
  517.             if (tp -> tun_flags & TUN_NBIO) {
  518.                 splx (s);
  519.                 return EWOULDBLOCK;
  520.             }
  521.             tp->tun_flags |= TUN_RWAIT;
  522.             sleep ((caddr_t) tp, PZERO + 1);
  523.         }
  524.     } while (m0 == 0);
  525.     splx (s);
  526.  
  527.     while (m0 && uio->uio_resid > 0 && error == 0) {
  528.         len = MIN (uio->uio_resid, m0->m_len);
  529.         if (len == 0)
  530.             break;
  531.         error = uiomove (mtod (m0, caddr_t), len,
  532.                  UIO_READ, uio);
  533.         MFREE (m0, m);
  534.         m0 = m;
  535.     }
  536.  
  537.     if (m0 != 0) {
  538.         TUNDEBUG ("Dropping mbuf\n");
  539.         m_freem (m0);
  540.     }
  541.     return error;
  542. }
  543.  
  544. /*
  545.  * the cdevsw write interface - an atomic write is a packet - or else!
  546.  */
  547.  
  548. tunwrite (dev, uio)
  549. int        dev;
  550. struct uio     *uio;
  551. {
  552.     int        error = 0;
  553.     int        unit = minor (dev);
  554.     struct mbuf    *top, **mp, *m;
  555.     struct ifnet   *ifp = &(tunctl[unit].tun_if);
  556.     int        s;
  557.  
  558.     TUNDEBUG ("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
  559.  
  560.     if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) {
  561.         TUNDEBUG ("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
  562.               uio->uio_resid);
  563.         return EIO;
  564.     }
  565.     top = 0;
  566.     mp = ⊤
  567.     while (error == 0 && uio->uio_resid > 0) {
  568.         MGET (m, M_DONTWAIT, MT_DATA);
  569.         if (m == 0) {
  570.             error = ENOBUFS;
  571.             break;
  572.         }
  573.         m->m_len = MIN (MLEN, uio->uio_resid);
  574.         error = uiomove (mtod (m, caddr_t), m->m_len, UIO_WRITE, uio);
  575.         *mp = m;
  576.         mp = &m->m_next;
  577.     }
  578.     if (error) {
  579.         if (top)
  580.             m_freem (top);
  581.         return error;
  582.     }
  583.  
  584. #ifdef BSD4_3
  585.     /*
  586.      * Place interface pointer before the data
  587.      * for the receiving protocol.
  588.      */
  589.     if (top->m_off <= MMAXOFF &&
  590.         top->m_off >= MMINOFF + sizeof(struct ifnet *)) {
  591.         top->m_off -= sizeof(struct ifnet *);
  592.         top->m_len += sizeof(struct ifnet *);
  593.     } else {
  594.         MGET(m, M_DONTWAIT, MT_HEADER);
  595.         if (m == (struct mbuf *)0)
  596.             return (ENOBUFS);
  597.         m->m_len = sizeof(struct ifnet *);
  598.         m->m_next = top;
  599.         top = m;
  600.     }
  601.     *(mtod(top, struct ifnet **)) = ifp;
  602. #endif /* BSD4_3 */
  603.  
  604.     s = splimp ();
  605.     if (IF_QFULL (&ipintrq)) {
  606.         IF_DROP (&ipintrq);
  607.         splx (s);
  608.         ifp->if_collisions++;
  609.         m_freem (top);
  610.         return ENOBUFS;
  611.     }
  612.     IF_ENQUEUE (&ipintrq, top);
  613.     splx (s);
  614.     ifp->if_ipackets++;
  615.     schednetisr (NETISR_IP);
  616.     return error;
  617. }
  618.  
  619. /*
  620.  * tunselect - the select interface, this is only useful on reads really.
  621.  * The write detect always returns true, write never blocks anyway, it either
  622.  * accepts the packet or drops it.
  623.  */
  624. tunselect (dev, rw)
  625. dev_t        dev;
  626. int        rw;
  627. {
  628.     int        unit = minor (dev);
  629.     register struct tunctl *tp = &tunctl[unit];
  630.     struct ifnet   *ifp = &tp->tun_if;
  631.     int        s = splimp ();
  632.  
  633.     TUNDEBUG ("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
  634.     switch (rw) {
  635.         case FREAD:
  636.         if (ifp->if_snd.ifq_len > 0) {
  637.             splx (s);
  638.             TUNDEBUG ("%s%d: tunselect q=%d\n", ifp->if_name,
  639.                   ifp->if_unit, ifp->if_snd.ifq_len);
  640.             return 1;
  641.         }
  642.         if (tp->tun_rsel && tp->tun_rsel->p_wchan ==
  643.             (caddr_t) & selwait)
  644.             tp->tun_flags |= TUN_RCOLL;
  645.         else
  646.             tp->tun_rsel = u.u_procp;
  647.         break;
  648.         case FWRITE:
  649.         splx (s);
  650.         return 1;
  651.     }
  652.     splx (s);
  653.     TUNDEBUG ("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
  654.     return 0;
  655. }
  656. #endif    NTUN
  657.